<template>
  <div class="wrap">
    <!-- 点击上传 -->
    <input ref="excelUploadInput" class="excel-upload-input" type="file" accept=".xlsx, .xls, .csv" @change="handleClick">
    <!-- 拖拽上传 -->
    <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
      {{ props.title }}
      <el-button :loading="loading" style="margin-left:16px;" size="small" type="primary" @click="handleUpload">
        点击上传
      </el-button>
    </div>
  </div>
</template>

<script setup>
import * as XLSX from 'xlsx'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const props = defineProps({
  title: String, // 上传组件显示标题
  beforeUpload: Function, // 判断文件类型和大小函数
  onSuccess: Function // 表格数据解析成功函数 
})

// 表单点击上传组件
const excelUploadInput = ref(null)
const loading = ref(false)
const excelData = ref({
  header: null,
  results: null
})

// 保存数据并回传出去
const generateData = ({ header, results }) => {
  excelData.value.header = header
  excelData.value.results = results
  props.onSuccess && props.onSuccess(excelData.value)
}

// drop 事件
const handleDrop = (e) => {
  e.stopPropagation()
  e.preventDefault()
  if (loading.value) return
  const files = e.dataTransfer.files
  if (files.length !== 1) {
    ElMessage.error('Only support uploading one file!')
    return
  }
  const rawFile = files[0] // only use files[0]

  if (!isExcel(rawFile)) {
    ElMessage.error('Only supports upload .xlsx, .xls, .csv suffix files')
    return false
  }
  upload(rawFile)
  e.stopPropagation()
  e.preventDefault()
}
const handleDragover = (e) => {
  e.stopPropagation()
  e.preventDefault()
  e.dataTransfer.dropEffect = 'copy'
}
// drop 内点击触发隐藏的 input 标签
const handleUpload = () => {
  excelUploadInput.value.click()
}

// 本地上传文件到浏览器触发
const handleClick = (e) => {
  const files = e.target.files
  const rawFile = files[0] // only use files[0]
  if (!rawFile) return
  upload(rawFile)
}

// 处理上传文件
const upload = (rawFile) => {
  excelUploadInput.value.value = null // fix can't select the same excel

  if (!props.beforeUpload) {
    readerData(rawFile)
    return
  }
  const before = props.beforeUpload(rawFile)
  if (before) {
    readerData(rawFile)
  }
}
const readerData = (rawFile) => {
  loading.value = true
  return new Promise((resolve) => {
    const reader = new FileReader()
    reader.onload = e => {
      const data = e.target.result
      const workbook = XLSX.read(data, { type: 'array' })
      const firstSheetName = workbook.SheetNames[0]
      const worksheet = workbook.Sheets[firstSheetName]
      const header = getHeaderRow(worksheet)
      const results = XLSX.utils.sheet_to_json(worksheet)
      generateData({ header, results })
      loading.value = false
      resolve()
    }
    reader.readAsArrayBuffer(rawFile)
  })
}
// 生成头部数据
const getHeaderRow = (sheet) => {
  const headers = []
  const range = XLSX.utils.decode_range(sheet['!ref'])
  let C
  const R = range.s.r
  /* start in the first row */
  for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
    const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
    /* find the cell in the first row */
    let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
    if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
    headers.push(hdr)
  }
  return headers
}

const isExcel = (file) => {
  return /\.(xlsx|xls|csv)$/.test(file.name)
}
</script>

<style scoped>
.excel-upload-input {
  display: none;
  z-index: -9999;
}
.wrap{
 display: inline-block;
}
.drop {
  border: 2px dashed #bbb;
  width: 300px;
  height: 150px;
  line-height: 160px;
  font-size: 16px;
  border-radius: 5px;
  text-align: center;
  color: #bbb;
  position: relative;
}
</style>
